package com.novax.ex.activity.provider.service;

import com.alibaba.fastjson.JSON;
import com.novax.ex.activity.infrastructure.entity.MallPrize;
import com.novax.ex.activity.infrastructure.entity.MallPrizeOrder;
import com.novax.ex.activity.infrastructure.mapper.MallPrizeMapper;
import com.novax.ex.activity.infrastructure.mapper.MallPrizeOrderMapper;
import com.novax.ex.activity.open.model.query.MallPrizeOrderQuery;
import com.novax.ex.activity.open.model.request.MallPrizeOrderRequest;
import com.novax.ex.activity.open.model.response.MallMsgResponse;
import com.novax.ex.activity.open.model.response.MallPrizeOrderResponse;
import com.novax.ex.activity.provider.api.InternationalApi;
import com.novax.ex.activity.provider.api.UserApi;
import com.novax.ex.activity.provider.api.UserAssetApi;
import com.novax.ex.activity.provider.api.model.UserAsset;
import com.novax.ex.activity.provider.api.model.UserDetailResponse;
import com.novax.ex.common.base.BaseMapper;
import com.novax.ex.common.base.BaseService;
import com.novax.ex.common.constant.InternationalCode;
import com.novax.ex.common.constant.StatusCode;
import com.novax.ex.common.core.redis.RedisDistributedLocker;
import com.novax.ex.common.core.redis.RedisLockUtil;
import com.novax.ex.common.enums.MallPrizeOrderStatus;
import com.novax.ex.common.enums.MallPrizeStatus;
import com.novax.ex.common.exception.BusinessException;
import com.novax.ex.common.results.ReturnResult;
import com.novax.ex.common.util.CopyUtils;
import com.novax.ex.common.util.PageUtil;
import com.novax.ex.common.util.Snowflake;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * @Description 用户购买记录表 service
 * @Author zhaolei
 * @Date 2/21/23 5:40 PM
 * @Version 1.0
 */
@Service
@Slf4j
public class MallPrizeOrderService extends BaseService {
    @Resource
    private MallPrizeOrderMapper mallPrizeOrderMapper;
    @Resource
    private MallPrizeMapper mallPrizeMapper;
    @Resource
    private InternationalApi internationalApi;
    @Resource
    private MallProductTitleLanguageService mallProductTitleLanguageService;
    @Resource
    private UserAssetApi userAssetApi;
    @Resource
    private RedisDistributedLocker redisLocker;
    @Resource
    private IeoOrderService ieoOrderService;//借用ieoserver方法中的操作现货逻辑
    @Resource
    private UserApi userApi;

    @Override
    protected BaseMapper getBaseMapper() {
        return mallPrizeOrderMapper;
    }

    /**
     * @description: 退款
     * @author: Wade
     * @date: 2/23/23 10:47 AM
     * @param: [order]
     * @return: void
     **/
    @Transactional
    public void refund(MallPrizeOrder order) {
        //退款
        ieoOrderService.assetOfChange(order.getUserId(), order.getId(), order.getCurrency(), order.getBuyPrice(), 80);
        //更改用户购买记录为退款
        MallPrizeOrder prizeOrder = new MallPrizeOrder();
        prizeOrder.setId(order.getId());
        prizeOrder.setStatus(MallPrizeOrderStatus.refund.getStatus());
        mallPrizeOrderMapper.updateByPrimaryKeySelective(prizeOrder);
    }

    /**
     * @description: 获取消息
     * @author: Wade
     * @date: 2/22/23 5:29 PM
     * @param: [language]
     * @return: java.util.List<com.novax.ex.activity.open.model.response.MallMsgResponse>
     **/
    public List<MallMsgResponse> msgList(String language) {
        //查询用户订单信息
        List<MallPrizeOrder> prizeOrders = mallPrizeOrderMapper.selectMsg();
        String msg = internationalApi.getInternational(InternationalCode.USER_MALL_ORDER_MSG, language).getData();
        List<MallMsgResponse> mallMsgResponses = new ArrayList<>();
        for (MallPrizeOrder prizeOrder : prizeOrders) {
            MallMsgResponse response = new MallMsgResponse();
            String title = mallProductTitleLanguageService.getTitleByLanguage(prizeOrder.getMallProductId(), language);
            response.setMessage(replaceMsg(prizeOrder.getNickname(), title, msg));
            mallMsgResponses.add(response);
        }
        return mallMsgResponses;
    }

    /**
     * @description: 替换手机号和商品名称
     * @author: Wade
     * @date: 2/22/23 8:37 PM
     * @param: [nickNmae, productName, msg]
     * @return: java.lang.String
     **/
    public static String replaceMsg(String nickNmae, String productName, String msg) {
        if (StringUtils.isBlank(msg)) {
            msg = "{0},{1}";
        }
        //替换用户手机号/邮箱
        if (StringUtils.isNotBlank(nickNmae)) {
            /*if (nickNmae.length() > 2) {
                nickNmae = getStar(nickNmae, 2, 0, "*");
            } else {
                //名称小于等于2
                nickNmae = nickNmae + "**";
            }*/
            //如果是邮件,开头是@说明是错误数据，就不按照邮件逻辑处理
            nickNmae = getNickName(nickNmae);
            msg = msg.replace("{0}", nickNmae);
        }
        if (StringUtils.isNotBlank(productName)) {
            //替换商品名称
            msg = msg.replace("{1}", productName);
        }
        return msg;
    }
    /**
     * @description: 昵称处理
     * @author: Wade
     * @date: 3/15/23 5:59 PM
     * @param: [nickNmae]
     * @return: java.lang.String
     **/
    public static String getNickName(String nickNmae){
        if (nickNmae.indexOf("@") > 0) {
            nickNmae = getEmailStar(nickNmae);
        } else {
            //非邮件
            nickNmae = getNonEmailStar(nickNmae);
        }
        return nickNmae;
    }

    /**
     * @description: 邮件规则
     * @author: Wade
     * @date: 3/13/23 3:50 PM
     * @param: []
     * @return: java.lang.String
     **/
    public static String getEmailStar(String nickNmae) {
        String[] split = nickNmae.split("@");
        String start = split[0];//@之前的字符
        String end = split[1];//@之后的字符
        //”superex.com/novax.email/superex.live/superex.biz”则自动转化为”gmail.com”.
        end = end.replace("superex.com","gmail.com")
                .replace("novax.email","gmail.com")
                .replace("superex.live","gmail.com")
                .replace("superex.biz","gmail.com")
                .replace("superex.email","gmail.com");
        if (start.length() <= 3) {
            if (start.length() == 1) {
                start = start+"**";
            }
            if (start.length() == 2) {
                start = start+"*";
            }
            if (start.length() == 3) {
                start = start.substring(0,2)+"*";
            }
        } else {
            start = getStar(start, 3, 0, "*");
        }
        /*if (end.length() <= 3) {
            if (end.length() == 1) {
                end = "*";
            }
            if (end.length() > 1) {
                end = getStar(end, 0, end.length() - 1, "*");
            }
        } else {
            end = getStar(end, 0, 3, "*");
        }*/
        return start + "@" + end;
    }

    /**
     * @description: 非邮件逻辑
     * @author: Wade
     * @date: 3/13/23 5:38 PM
     * @param: [nickNmae]
     * @return: java.lang.String
     **/
    public static String getNonEmailStar(String nickNmae) {
        if(nickNmae.length()<4){
            if (nickNmae.length() == 1) {
                nickNmae = nickNmae+"***";
            }
            if (nickNmae.length() == 2) {
                nickNmae = nickNmae+"**";
            }
            if (nickNmae.length() == 3) {
                nickNmae = nickNmae+"*";
            }
        }else if(nickNmae.length()>=4 && nickNmae.length()<8){
            nickNmae = getStar(nickNmae, 2, 1, "*");
        }else{
            nickNmae = getStar(nickNmae, 4, 3, "*");
        }
        return nickNmae;
    }

    /**
     * @description: 设置小星星
     * @author: Wade
     * @date: 2/23/23 8:23 PM
     * @param: [content, frontNum, endNum, rep]
     * @return: java.lang.String
     **/
    public static String getStar(String content, int frontNum, int endNum, String replace) {
        if (frontNum >= content.length() || frontNum < 0) {
            return content;
        }
        if (endNum >= content.length() || endNum < 0) {
            return content;
        }
        if (frontNum + endNum >= content.length()) {
            return content;
        }
        String starStr = "";
        for (int i = 0; i < (content.length() - frontNum - endNum); i++) {
            starStr = starStr + replace;
        }
        return content.substring(0, frontNum) + starStr
                + content.substring(content.length() - endNum);
    }

    public static void main(String[] args) {
        //System.out.println(replaceMsg("1", "商品名称","你好{0}你中奖了{1}"));
        String s1 = "1@1";
        System.out.println("原数据：" + s1 + "处理后：" + getEmailStar(s1));
        s1 = "12@1";
        System.out.println("原数据：" + s1 + "处理后：" + getEmailStar(s1));
        s1 = "123@11";
        System.out.println("原数据：" + s1 + "处理后：" + getEmailStar(s1));
        s1 = "1234@11";
        System.out.println("原数据：" + s1 + "处理后：" + getEmailStar(s1));
        s1 = "12345@11";
        System.out.println("原数据：" + s1 + "处理后：" + getEmailStar(s1));
        s1 = "123456@11";
        System.out.println("原数据：" + s1 + "处理后：" + getEmailStar(s1));
        s1 = "1234567@11";
        System.out.println("原数据：" + s1 + "处理后：" + getEmailStar(s1));

        s1 = "1@superex.com";
        System.out.println("原数据：" + s1 + "处理后：" + getEmailStar(s1));
        s1 = "1@novax.email";
        System.out.println("原数据：" + s1 + "处理后：" + getEmailStar(s1));
        s1 = "1@superex.live";
        System.out.println("原数据：" + s1 + "处理后：" + getEmailStar(s1));
        s1 = "1@superex.biz";
        System.out.println("原数据：" + s1 + "处理后：" + getEmailStar(s1));


        s1 = "1";
        System.out.println("原数据：" + s1 + "处理后：" + getNonEmailStar(s1));
        s1 = "12";
        System.out.println("原数据：" + s1 + "处理后：" + getNonEmailStar(s1));
        s1 = "123";
        System.out.println("原数据：" + s1 + "处理后：" + getNonEmailStar(s1));
        s1 = "1234";
        System.out.println("原数据：" + s1 + "处理后：" + getNonEmailStar(s1));

        s1 = "12345";
        System.out.println("原数据：" + s1 + "处理后：" + getNonEmailStar(s1));
        s1 = "123456";
        System.out.println("原数据：" + s1 + "处理后：" + getNonEmailStar(s1));
        s1 = "1234567";
        System.out.println("原数据：" + s1 + "处理后：" + getNonEmailStar(s1));

        s1 = "12345678";
        System.out.println("原数据：" + s1 + "处理后：" + getNonEmailStar(s1));
        s1 = "123456789";
        System.out.println("原数据：" + s1 + "处理后：" + getNonEmailStar(s1));

        s1 = "123456789abcdefg";
        System.out.println("原数据：" + s1 + "处理后：" + getNonEmailStar(s1));
    }

    /**
     * @description: 支付购买
     * @author: Wade
     * @date: 2/23/23 10:45 AM
     * @param: [userId, language, orderRequest]
     * @return: com.novax.ex.common.results.ReturnResult<?>
     **/
    @Transactional
    public ReturnResult<MallPrizeOrder> buy(Long userId, String language, MallPrizeOrderRequest orderRequest) {
        //统一错误归并提示
        String msg = internationalApi.getInternational(InternationalCode.USER_MALL_ORDER_BUY_FAIL, language).getData();
        //加分布式锁防止多卖，一次针对这个商品池商品只有一个人在同时下单
        String orderLockKey = RedisLockUtil.ORDER_LOCK + orderRequest.getMallPrizeId();
        boolean orderLock = redisLocker.tryLock(orderLockKey, false);// 给订单加锁
        try {
            if (orderLock) {
                //判断购买份数是否大于0，否则返回错误
                if (orderRequest.getAmount().intValue() <= 0) {
                    return ReturnResult.fail(internationalApi.getInternational(InternationalCode.REQUIREMENT, language).getData());
                }
                MallPrize mallPrize = mallPrizeMapper.selectByPrimaryKey(orderRequest.getMallPrizeId());
                //验证数据是否有效
                if (Objects.isNull(mallPrize)) {
                    redisLocker.unlock(orderLockKey);
                    return ReturnResult.fail(internationalApi.getInternational(InternationalCode.NOT_EXIST, language).getData());
                } else {
                    //如果状态不是进行中那么也认为数据不存在
                    if (!mallPrize.getStatus().equals(MallPrizeStatus.start.getStatus())) {
                        redisLocker.unlock(orderLockKey);
                        msg = internationalApi.getInternational(InternationalCode.USER_MALL_ORDER_BUY_ERR, language).getData();
                        return new ReturnResult<>(StatusCode.ALERT_ERROR, msg);
                    }
                }
                String title = mallProductTitleLanguageService.getTitleByLanguage(mallPrize.getMallProductId(), language);
                String nickName = getNickName(userId);
                //本次下单金额
                BigDecimal price = mallPrize.getMinPrice().multiply(new BigDecimal(orderRequest.getAmount()));
                if (checkBuyPrice(price, userId, mallPrize.getCurrency())) {
                    long orderId = Snowflake.generateId();
                    //支付扣款
                    ReturnResult assetResult = ieoOrderService.assetOfChange(userId, orderId, mallPrize.getCurrency(), price, 79);
                    //判断扣款状态是否成功
                    if (Objects.nonNull(assetResult) && assetResult.isSuccess()) {
                        //插入订单
                        MallPrizeOrder mallPrizeOrder = addOrder(orderId, userId, price, orderRequest.getAmount(), title, nickName, mallPrize);
                        msg = internationalApi.getInternational(InternationalCode.USER_MALL_ORDER_SUCCESS, language).getData();
                        redisLocker.unlock(orderLockKey);
                        return new ReturnResult(StatusCode.SUCCESS, msg, mallPrizeOrder);
                    }
                } else {
                    redisLocker.unlock(orderLockKey);
                    msg = internationalApi.getInternational(InternationalCode.USER_MALL_ORDER_FAIL, language).getData();
                    return new ReturnResult<>(StatusCode.CREDIT_RUN_LOW, msg);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("一元购支付失败:用户ID" + userId + "请求参数" + JSON.toJSONString(orderRequest));
            throw new BusinessException("mall buy invalid");
        } finally {
            redisLocker.unlock(orderLockKey);
        }
        return ReturnResult.fail(msg);
    }

    /**
     * @description: 插入用户订单
     * @author: Wade
     * @date: 2/24/23 2:21 PM
     * @param: [orderId, userId, price, amount, title, nickName, mallPrize]
     * @return: void
     **/
    private MallPrizeOrder addOrder(Long orderId, Long userId, BigDecimal price, Integer amount, String title, String nickName, MallPrize mallPrize) {
        //扣款成功，进行用户订单插入
        MallPrizeOrder mallPrizeOrder = CopyUtils.copyObject(mallPrize, MallPrizeOrder.class);
        //设置快照名称
        mallPrizeOrder.setId(orderId);
        mallPrizeOrder.setUserId(userId);
        mallPrizeOrder.setNickname(nickName);
        mallPrizeOrder.setMallPrizeId(mallPrize.getId());
        mallPrizeOrder.setSnapshotTitle(title);
        mallPrizeOrder.setBuyCount(amount);
        mallPrizeOrder.setBuyPrice(price);
        mallPrizeOrder.setStatus(MallPrizeOrderStatus.stay.getStatus());
        mallPrizeOrder.setCreateTime(null);
        mallPrizeOrder.setUpdateTime(null);
        addSelective(mallPrizeOrder);
        //修改奖品池相关信息
        MallPrize prize = new MallPrize();
        prize.setId(mallPrize.getId());
        prize.setSellCount(mallPrize.getSellCount() + amount);
        prize.setSellPrice(mallPrize.getSellPrice().add(price));
        //如果售卖价格>=指定价格 设置为完成,这样后面的就不会在进来了
        if (prize.getSellPrice().compareTo(mallPrize.getPrice()) >= 0) {
            prize.setStatus(MallPrizeStatus.over.getStatus());
        }
        mallPrizeMapper.updateByPrimaryKeySelective(prize);
        return mallPrizeOrder;
    }

    /**
     * @description: 获取用户昵称
     * @author: Wade
     * @date: 2/24/23 2:04 PM
     * @param: [userId]
     * @return: java.lang.String
     **/
    private String getNickName(Long userId) {
        //获取用户
        try {
            ReturnResult<UserDetailResponse> userResult = userApi.detail(userId);
            if (userResult.isSuccess() && Objects.nonNull(userResult.getData())) {
                UserDetailResponse response = userResult.getData();
                if (StringUtils.isNotBlank(response.getPhone())) {
                    return response.getPhone();
                }
                if (StringUtils.isNotBlank(response.getEmail())) {
                    return response.getEmail();
                }
                if (StringUtils.isNotBlank(response.getAuthEmail())) {
                    return response.getAuthEmail();
                }
                if (StringUtils.isNotBlank(response.getAddress())) {
                    return response.getAddress();
                }
            }
        } catch (Exception ex) {
            //获取用户信息，如果失败直接吃掉异常，不允许影响主业务
        }
        return "unknown";
    }

    /**
     * @description: 查询余额是否充足
     * @author: Wade
     * @date: 2/24/23 9:41 AM
     * @param: [price, userId, currency]
     * @return: boolean
     **/
    private boolean checkBuyPrice(BigDecimal price, Long userId, String currency) {
        ReturnResult<UserAsset> assetReturnResult = userAssetApi.findAsset(userId, currency);
        if (Objects.nonNull(assetReturnResult) && Objects.nonNull(assetReturnResult.getData())) {
            //判断账户余额是否大于本次需要支付的金额
            if (assetReturnResult.getData().getAvailable().compareTo(price) >= 0) {
                return true;
            }
        }
        log.error("一元购支付查询资产失败:用户ID" + userId + "请求金额" + price.toString());
        return false;
    }


    /**
     * @description: 查询参与列表
     * @author: Wade
     * @date: 2/23/23 10:45 AM
     * @param: [userId, language, query]
     * @return: com.novax.ex.common.results.ReturnResult<com.novax.ex.common.util.PageUtil < com.novax.ex.activity.open.model.response.MallPrizeOrderResponse>>
     **/
    public ReturnResult<PageUtil<MallPrizeOrderResponse>> list(Long userId, String language, MallPrizeOrderQuery
            query) {
        PageUtil<MallPrizeOrderResponse> page = new PageUtil<>(query);
        query.setUserId(userId);
        page.setCondition(Collections.singletonMap("query", query));
        findPage(page, MallPrizeOrderResponse.class);
        return ReturnResult.success(page);
    }

    /**
     * @description: 查询是否存在中奖未领取的
     * @author: Wade
     * @date: 2/23/23 10:45 AM
     * @param: [userId]
     * @return: java.lang.Boolean
     **/
    public MallPrizeOrder unclaimed(Long userId) {
        return mallPrizeOrderMapper.unclaimed(userId);
    }

    /**
     * @description: 通过奖池商品ID批量更新订单记录为参与状态
     * @author: Wade
     * @date: 2/25/23 10:55 AM
     * @param: [mallPrizeId]
     * @return: void
     **/
    public void updateParticipated(Long mallPrizeId) {
        mallPrizeOrderMapper.updateParticipated(mallPrizeId);
    }

    /**
     * Description: 商品参与报表
     *
     * @author Deucalion@novax.email
     * @date 2023/3/16 11:33
     */
    public <T> void participationRecordPage(PageUtil<T> pageInfo, Class<T> clazz) {
        long total = mallPrizeOrderMapper.participationRecordCount(pageInfo);
        pageInfo.setTotal(total);
        if (total > 0) {
            pageInfo.setItems(CopyUtils.copyList(mallPrizeOrderMapper.participationRecordPage(pageInfo), clazz));
        } else {
            pageInfo.setItems(new ArrayList<>());
        }
    }

    /**
     * Description: 支付记录查询
     *
     * @author Deucalion@novax.email
     * @date 2023/10/10 9:07
     */
    public <T> void paymentRecordPage(PageUtil<T> pageInfo, Class<T> clazz) {
        long total = mallPrizeOrderMapper.paymentRecordCount(pageInfo);
        pageInfo.setTotal(total);
        if (total > 0) {
            pageInfo.setItems(CopyUtils.copyList(mallPrizeOrderMapper.paymentRecordPage(pageInfo), clazz));
        } else {
            pageInfo.setItems(new ArrayList<>());
        }
    }
}
